package yzrilyzr.simplesynth.app.view;
import static yzrilyzr.util.WidgetUtil.px;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.View;

import yzrilyzr.icondesigner.VECfile;
import yzrilyzr.util.Util;

public class SimpleKeyboardView extends View{
	// 使用SparseArray替代HashMap，性能更好
	private final SparseArray<Integer> activePointers=new SparseArray<>();
	private final SparseArray<Integer> pressedKeys=new SparseArray<>();
	public void setKeyboardCallback(KeyboardCallback keyboardCallback){
		this.keyboardCallback=keyboardCallback;
	}
	private KeyboardCallback keyboardCallback=null;
	Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
	String[] str=new String[]{"do","re","mi","fa","so","la","ti"};
	VECfile vec;
	int[] pitch=new int[]{0,2,4,5,7,9,11};
	public SimpleKeyboardView(Context ctx,AttributeSet attr){
		super(ctx,attr);
		vec=VECfile.fromAssets(ctx,"simplekey");
	}
	@Override
	public boolean onTouchEvent(MotionEvent event){
		int pointerIndex=event.getActionIndex();
		int pointerId=event.getPointerId(pointerIndex);
		int action=event.getActionMasked();
		switch(action){
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_POINTER_DOWN:{
				int key=getKeyForPosition(event.getX(pointerIndex),event.getY(pointerIndex));
				if(key!=-1){
					activePointers.put(pointerId,key);
					pressedKeys.put(key,pointerId);
					onDown(key,event.getPressure(pointerIndex));
					invalidate();
				}
				break;
			}
			case MotionEvent.ACTION_MOVE:{
				for(int i=0;i<event.getPointerCount();i++){
					pointerId=event.getPointerId(i);
					int oldKey=activePointers.get(pointerId,-1);
					int newKey=getKeyForPosition(event.getX(i),event.getY(i));
					if(oldKey!=newKey){
						if(oldKey!=-1){
							pressedKeys.delete(oldKey);
							onUp(oldKey);
						}
						if(newKey!=-1){
							activePointers.put(pointerId,newKey);
							pressedKeys.put(newKey,pointerId);
							onDown(newKey,event.getPressure(i));
						}
					}
				}
				invalidate();
				break;
			}
			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_POINTER_UP:
			case MotionEvent.ACTION_CANCEL:{
				int key=activePointers.get(pointerId,-1);
				if(key!=-1){
					activePointers.remove(pointerId);
					pressedKeys.delete(key);
					onUp(key);
					invalidate();
				}
				break;
			}
		}
		return true;
	}
	private int getKeyForPosition(float x,float y){
		int siz=px(50);
		int w=getWidth(), h=getHeight();
		int marginH=px(20), marginV=px(20);
		int totalW=6*marginH+7*siz;
		int totalH=4*marginV+5*siz;
		int borderH=(w-totalW)/2;
		int borderV=(h-totalH)/2;
		Rect r=new Rect();
		int yAdv=0;
		for(int j=0;j<5;j++){
			int xAdv=0;
			for(int i=0;i<7;i++){
				r.set(borderH+xAdv,borderV+yAdv,
					  borderH+siz+xAdv,borderV+siz+yAdv);
				if(r.contains((int)x,(int)y)){
					return 48+pitch[i]+(4-j)*12;
				}
				xAdv+=siz+marginH;
			}
			yAdv+=siz+marginV;
		}
		return -1;
	}
	@Override
	protected void onDraw(Canvas canvas){
		int siz=px(50);
		int w=getWidth(), h=getHeight();
		int marginH=px(20), marginV=px(20);
		int totalW=6*marginH+7*siz;
		int totalH=4*marginV+5*siz;
		int borderH=(w-totalW)/2;
		int borderV=(h-totalH)/2;
		paint.setStyle(Paint.Style.FILL);
		int yAdv=0;
		for(int j=0;j<5;j++){
			int xAdv=0;
			for(int i=0;i<7;i++){
				int key=48+pitch[i]+(4-j)*12;
				vec.setBounds(borderH+xAdv,borderV+yAdv,
							  borderH+siz+xAdv,borderV+siz+yAdv);
				vec.getShapes().get(2).txt=str[i];
				vec.getShapes().get(0).setColor(pressedKeys.indexOfKey(key)>=0?
														0xff808080:0xfffff6dc);
				vec.draw(canvas);
				xAdv+=siz+marginH;
			}
			yAdv+=siz+marginV;
		}
	}
	private void onUp(int key){
		if(keyboardCallback!=null) keyboardCallback.noteOff(key-12);
	}
	private void onDown(int key,float pressure){
		if(keyboardCallback!=null)
			keyboardCallback.noteOn(key-12,Util.clamp((int)(pressure*127),0,127));
	}
}